package com.chongchong.flow.listener;

import com.alibaba.fastjson.JSONObject;
import com.chongchong.common.tool.EmailCommonUtil;
import com.chongchong.core.secure.utils.SecureUtil;
import com.chongchong.core.tool.api.R;
import com.chongchong.core.tool.context.ApplicationContextHolder;
import com.chongchong.core.tool.utils.Func;
import com.chongchong.core.tool.utils.StringUtil;
import com.chongchong.flow.entity.FlowTaskComment;
import com.chongchong.flow.service.IFlowTaskCommentService;
import com.chongchong.system.entity.EmailTemplate;
import com.chongchong.user.entity.User;
import com.chongchong.user.entity.UserInfo;
import com.chongchong.user.feign.IEmailClient;
import com.chongchong.user.feign.IUserClient;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.delegate.ExecutionListener;
import org.activiti.engine.delegate.TaskListener;
import org.activiti.engine.impl.el.FixedValue;
import org.activiti.engine.impl.persistence.entity.VariableInstance;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 */
@Slf4j
public class SendEmailListener implements TaskListener, ExecutionListener {

	/**
	 * 审批（通用）
	 */
	private FixedValue approval;
	/**
	 * 流程流转（通用）
	 */
	private FixedValue processTurn;
	/**
	 * 发起人发起提醒（通用）
	 */
	private FixedValue startNotice;
	/**
	 * 流程完成提醒（通用）
	 */
	private FixedValue  complete;
	/**
	 * 包材审批
	 */
	private FixedValue pkgApproval;
	/**
	 * 包材流程流转
	 */
	private FixedValue pkgProcessTurn;
	/**
	 * 远程测试流转
	 */
	private FixedValue remoteProcessTurn;
	/**
	 * 新品供应商复制驳回通知
	 */
	private FixedValue supplierCopyRefuse;
	/**
	 * 在线移交流程流转
	 */
	private FixedValue handOverProcessTurn;
	/**
	 * STAR审核流程流转
	 */
	private FixedValue starProcessTurn;

	private final EmailCommonUtil emailCommonUtil = ApplicationContextHolder.getBean(EmailCommonUtil.class);
	private final IUserClient userClient = ApplicationContextHolder.getBean(IUserClient.class);
	private final IEmailClient emailClient = ApplicationContextHolder.getBean(IEmailClient.class);
	private final IFlowTaskCommentService flowTaskCommentService = ApplicationContextHolder.getBean(IFlowTaskCommentService.class);

	@Override
	public void notify(DelegateTask delegateTask) {
		Map<String, Object> variables1 = delegateTask.getVariables();

	}

	@Override
	public void notify(DelegateExecution delegateExecution) {
		try {
			log.info("审批流程配置参数-----------"+approval);
			log.info("流程流转配置参数-----------"+processTurn);
			log.info("发起人发起提醒配置参数-----------"+startNotice);
			log.info("流程完成提醒配置参数------------"+complete);
			log.info("包材审批流程配置参数------------"+pkgApproval);
			log.info("包材流程流转配置参数------------"+pkgProcessTurn);
			log.info("远程测试流程流转配置参数---------"+remoteProcessTurn);
			log.info("新品供应商复制驳回配置参数--------"+supplierCopyRefuse);
			log.info("在线移交流程流转配置参数-----------"+handOverProcessTurn);
			log.info("STAR审核流程流转配置参数----------"+starProcessTurn);
			//流程参数
			Map<String, VariableInstance> variables = delegateExecution.getVariableInstances();
			//处理发起人发起流程提醒
			if (startNotice != null){
				//流程图监听器封装的json数据
				JSONObject params = JSONObject.parseObject(String.valueOf(startNotice.getValue(null)));
				log.info("发起人发起提醒配置参数json-----------"+params);
				//邮件模板id
				String emailTemplateId = params.getString("emailTemplateId");
				//模块名称
				String processName = params.getString("processName");
				//邮件模板id不为空
				if (StringUtil.hasText(emailTemplateId)) {
					//根据模板id查询邮件模板
					EmailTemplate tpm = emailClient.findByTemplateId(emailTemplateId);
					if (tpm != null && tpm.getId() != null) {
						//获取当前登陆人
						Long userId = SecureUtil.getUser().getUserId();
						//根据id查询用户
						R<UserInfo> user = userClient.userInfo(userId);
						if (user.isSuccess()&&user.getData()!=null&&user.getData().getUser()!=null&&StringUtil.hasText(user.getData().getUser().getEmail())){
							String email = user.getData().getUser().getEmail();
							//获取项目编号和名称
							Map<String,Object> templateParam = getProjectAndName(variables);
							templateParam.put("processName",processName);
							new Thread(()->{
								log.info("发起人发起提醒异步发送邮箱任务开始----------->"+ System.currentTimeMillis());
								//发送邮件
								emailCommonUtil.sendMail(Func.toStrList(email), tpm.getEmailTheme(), tpm.getEmailTheme(), processTemplate(tpm.getMouldContent(),templateParam));
								log.info("发起人发起提醒异步发送邮箱任务结束----------->"+ System.currentTimeMillis());
							}).start();
						}
					}
				}
			}
			//处理审批流程
			if (approval != null) {
				//驳回不处理
				if (isRefuse(variables)){
					return;
				}
				//流程图监听器封装的json数据
				JSONObject params = JSONObject.parseObject(String.valueOf(approval.getValue(null)));
				log.info("审批流程配置参数json-----------"+params);
				//不满足审批
				if (!isAccordWithApproval(variables,params)){
					return;
				}
				//邮件模板id
				String emailTemplateId = params.getString("emailTemplateId");
				//模块名称
				String processName = params.getString("processName");
				String taskName = params.getString("taskName");
				//邮件模板id不为空
				if (StringUtil.hasText(emailTemplateId)) {
					//根据模板id查询邮件模板
					EmailTemplate tpm = emailClient.findByTemplateId(emailTemplateId);
					if (tpm != null && tpm.getId() != null) {
						//审批人key
						String approvalPersonName = params.getString("approvalPerson");
						if (StringUtil.hasText(approvalPersonName)){
							String name = "";
							if (approvalPersonName.contains("_")){
								String[] names = approvalPersonName.split("\\_");
								if (variables.get("requireDepartment")!=null&&"1".equals(variables.get("requireDepartment").getTextValue())){
									//品牌
									name = names[0];
								}else if (variables.get("requireDepartment")!=null&&"2".equals(variables.get("requireDepartment").getTextValue())){
									//RE
									name = names[1];
								}
							}else{
								name = approvalPersonName;
							}
							//根据用户获取邮箱
							String email = getEmailByName(name,variables);
							if (StringUtil.hasText(email)){
								Map<String,Object> templateParam = null;
								if (StringUtil.hasText(taskName)&&"成品抽检".equals(taskName)){
									templateParam = getSpotCheckParam(variables);
								}else{
									templateParam = getProjectAndName(variables);
								}
								templateParam.put("processName",processName);
								final Map<String,Object> param = templateParam;
								new Thread(()->{
									log.info("审批流程异步发送邮箱任务开始----------->"+ System.currentTimeMillis());
									//发送邮件
									emailCommonUtil.sendMail(Func.toStrList(email), tpm.getEmailTheme(), tpm.getEmailTheme(), processTemplate(tpm.getMouldContent(),param));
									log.info("审批流程异步发送邮箱任务结束----------->"+ System.currentTimeMillis());
								}).start();
							}
						}else{ //审批人是角色
							String approvalRole = params.getString("approvalRole");
							String taskKey = params.getString("taskKey");
							if(StringUtil.hasText(taskKey)){
								//获取流程发起人
								User user1 = getStartUser(delegateExecution,params,variables);
								if (user1 != null && StringUtil.hasText(user1.getEmail())){
									String email = user1.getEmail();
									//获取项目编号和名称
									Map<String,Object> templateParam = getProjectAndName(variables);
									templateParam.put("processName",processName);
									new Thread(()->{
										log.info("审批流程异步发送邮箱任务开始----------->"+ System.currentTimeMillis());
										//发送邮件
										emailCommonUtil.sendMail(Func.toStrList(email), tpm.getEmailTheme(), tpm.getEmailTheme(), processTemplate(tpm.getMouldContent(),templateParam));
										log.info("审批流程异步发送邮箱任务结束----------->"+ System.currentTimeMillis());
									}).start();
								}
							} else {
								//根据角色获取所有的邮箱
								List<String> emails = findEmailByRole(approvalRole);
								if (emails.size()>0){
									//获取项目编号和名称
									Map<String,Object> templateParam = getProjectAndName(variables);
									templateParam.put("processName",processName);
									new Thread(()->{
										log.info("审批流程(角色)异步发送邮箱任务开始----------->"+ System.currentTimeMillis());
										//发送邮件
										emailCommonUtil.sendMail(emails, tpm.getEmailTheme(), tpm.getEmailTheme(), processTemplate(tpm.getMouldContent(),templateParam));
										log.info("审批流程(角色)异步发送邮箱任务结束----------->"+ System.currentTimeMillis());
									}).start();
								}
							}
						}
					}
				}
			}
			//处理流转流程
			if (processTurn != null){
				//驳回不处理
				if (isRefuse(variables)){
					return;
				}
				//若不是supervisor角色,走三级审批
				if (variables.get("isSupervisorRole")!=null && "1".equals(variables.get("isSupervisorRole").getTextValue())){
					return;
				}
				//流程图监听器封装的json数据
				JSONObject params = JSONObject.parseObject(String.valueOf(processTurn.getValue(null)));
				log.info("流程流转配置参数json-----------"+params);
				//邮件模板id
				String emailTemplateId = params.getString("emailTemplateId");
				//模块名称
				String processName = params.getString("processName");
				//状态
				String status = params.getString("status");
				//邮件模板id不为空
				if (StringUtil.hasText(emailTemplateId)) {
					//根据模板id查询邮件模板
					EmailTemplate tpm = emailClient.findByTemplateId(emailTemplateId);
					if (tpm != null && tpm.getId() != null) {
						//获取下级处理人key
						String handlePersonName = params.getString("handlePersonName");
						//下级处理人不为空
						if (StringUtil.hasText(handlePersonName)){
							String name = "";
							if (handlePersonName.contains("_")){
								String[] names = handlePersonName.split("\\_");
								if (variables.get("devicePropertyOne") != null){
									String devicePropertyOne = variables.get("devicePropertyOne").getTextValue();
									//定制
									if ("1".equals(devicePropertyOne)){
										//pcm
										name = names[0];
									}else if ("2".equals(devicePropertyOne)){ //通路
										//供应商
										name = names[1];
									}
								}else if (variables.get("requireDepartment") != null){
									String requireDepartment = variables.get("requireDepartment").getTextValue();
									if ("1".equals(requireDepartment)){
										//品牌
										name = names[0];
									}else if ("2".equals(requireDepartment)){
										//RE
										name = names[1];
									}
								}
							}else{
								name = handlePersonName;
							}
							//根据用户获取邮箱
							String email = getEmailByName(name,variables);
							if (StringUtil.hasText(email)){
								final String userEmail = email;
								//获取项目编号和名称
								Map<String,Object> templateParam = getProjectAndName(variables);
								User user1 = getStartUser(delegateExecution,params,variables);
								templateParam.put("startUserName", user1!=null?user1.getName():"");
								templateParam.put("processName",processName);
								templateParam.put("status",status);
								new Thread(()->{
									log.info("流程流转异步发送邮箱任务开始----------->"+ System.currentTimeMillis());
									//发送邮件
									emailCommonUtil.sendMail(Func.toStrList(userEmail), tpm.getEmailTheme(), tpm.getEmailTheme(), processTemplate(tpm.getMouldContent(),templateParam));
									log.info("流程流转异步发送邮箱任务结束----------->"+ System.currentTimeMillis());
								}).start();
							}
						}else{ //下级处理人为空，是角色
							//获取下级处理人角色
							String handlePersonRole = params.getString("handlePersonRole");
							if (StringUtil.hasText(handlePersonRole)) {
								//获取流程发起人
								User user1 = getStartUser(delegateExecution, params, variables);
								if (user1 != null && StringUtil.hasText(user1.getEmail())) {
									String email = user1.getEmail();
									//获取项目编号和名称
									Map<String, Object> templateParam = getProjectAndName(variables);
									templateParam.put("startUserName", user1 != null ? user1.getName() : "");
									templateParam.put("processName", processName);
									templateParam.put("status", status);
									new Thread(() -> {
										log.info("流程流转（角色）异步发送邮箱任务开始----------->" + System.currentTimeMillis());
										//发送邮件
										emailCommonUtil.sendMail(Func.toStrList(email), tpm.getEmailTheme(), tpm.getEmailTheme(), processTemplate(tpm.getMouldContent(), templateParam));
										log.info("流程流转（角色）异步发送邮箱任务结束----------->" + System.currentTimeMillis());
									}).start();
								}
							}
						}
					}
				}
			}
			//处理流程结束提醒
			if (complete != null){
				//驳回不处理
				if (isRefuse(variables)){
					return;
				}
				//流程图监听器封装的json数据
				JSONObject params = JSONObject.parseObject(String.valueOf(complete.getValue(null)));
				log.info("流程完成提醒配置参数json-----------"+params);
				//邮件模板id
				String emailTemplateId = params.getString("emailTemplateId");
				//模块名称
				String processName = params.getString("processName");
				//邮件模板id不为空
				if (StringUtil.hasText(emailTemplateId)) {
					//根据模板id查询邮件模板
					EmailTemplate tpm = emailClient.findByTemplateId(emailTemplateId);
					if (tpm != null && tpm.getId() != null) {
						//获取流程发起人
						User user = getStartUser(delegateExecution,params,variables);
						//邮箱存在
						if (user!=null && StringUtil.hasText(user.getEmail())){
							//获取项目编号和名称
							Map<String,Object> templateParam = getProjectAndName(variables);
							templateParam.put("processName",processName);
							new Thread(()->{
								log.info("流程完成异步发送邮箱任务开始----------->"+ System.currentTimeMillis());
								//发送邮件
								emailCommonUtil.sendMail(Func.toStrList(user.getEmail()), tpm.getEmailTheme(), tpm.getEmailTheme(), processTemplate(tpm.getMouldContent(),templateParam));
								log.info("流程完成异步发送邮箱任务结束----------->"+ System.currentTimeMillis());
							}).start();
						}
					}
				}
			}
		}catch (Exception e){
			e.printStackTrace();
			log.info("发送邮件出错-----"+e.getMessage());
		}
	}


	/**
	 * 处理动态参数
	 * @param template
	 * @param params
	 * @return
	 */
	private String processTemplate(String template, Map<String, Object> params){
		StringBuffer sb = new StringBuffer();
		Matcher m = Pattern.compile("\\$\\{\\w+\\}").matcher(template);
		while (m.find()) {
			String param = m.group();
			Object value = params.get(param.substring(2, param.length() - 1));
			m.appendReplacement(sb, value==null ? "" : value.toString());
		}
		m.appendTail(sb);
		return sb.toString();
	}

	/**
	 *
	 * 获取项目编号和名称
	 * @param variables
	 * @return
	 */
	private Map<String,Object> getProjectAndName(Map<String, VariableInstance> variables){
		Map<String,Object> map = new HashMap<>();
		String projectNo = "";
		String projectName = "";
		if (variables.get("projectNo")!=null && StringUtil.hasText(variables.get("projectNo").getTextValue())){
			projectNo = variables.get("projectNo").getTextValue();
		}
		if (variables.get("projectName")!=null && StringUtil.hasText(variables.get("projectName").getTextValue())){
			projectName = variables.get("projectName").getTextValue();
		}
		map.put("projectNo",projectNo);
		map.put("projectName",projectName);
		return map;
	}

	/**
	 * 获取成品抽检单据号和业务名称
	 * @param variables
	 * @return
	 */
	private Map<String,Object> getSpotCheckParam(Map<String, VariableInstance> variables){
		Map<String,Object> map = new HashMap<>();
		String businessNo = "";
		String businessName = "";
		if (variables.get("businessNo")!=null && StringUtil.hasText(variables.get("businessNo").getTextValue())){
			businessNo = variables.get("businessNo").getTextValue();
		}
		if (variables.get("businessName")!=null && StringUtil.hasText(variables.get("businessName").getTextValue())){
			businessName = variables.get("businessName").getTextValue();
		}
		map.put("businessNo",businessNo);
		map.put("businessName",businessName);
		return map;
	}

	/**
	 * 判断是否是驳回
	 * @param variables
	 * @return
	 */
	private Boolean isRefuse(Map<String, VariableInstance> variables){
		VariableInstance operationTypeIns = variables.get("operationType");
		if (operationTypeIns != null && "refuse".equals(operationTypeIns.getTextValue())){
			return true;
		}
		return false;
	}

	/**
	 * 判断是否满足审批
	 * @param variables
	 * @param params
	 * @return
	 */
	private Boolean isAccordWithApproval(Map<String, VariableInstance> variables,JSONObject params){
		String approvalPersonName = params.getString("approvalPerson");
		String nextTaskName = params.getString("nextTaskName");
		String isStart = params.getString("isStart");
		if (!StringUtil.hasText(approvalPersonName)
			|| (StringUtil.hasText(nextTaskName)&&"三级审批".equals(nextTaskName)
			&& variables.get("isSupervisorRole")!=null
			&& "2".equals(variables.get("isSupervisorRole").getTextValue()))){
			return false;
		}
		//标准化移交
		if (StringUtil.hasText(isStart)&&variables.get("handOverType")!=null&&"0".equals(variables.get("handOverType").getTextValue())){
			return false;
		}
		return true;
	}

	/**
	 * 获取发起人
	 * @param delegateExecution
	 * @param params
	 * @return
	 */
	private User getStartUser(DelegateExecution delegateExecution,JSONObject params,Map<String, VariableInstance> variables){
		//获取流程instanceId
		String processInstanceId = delegateExecution.getProcessInstanceId();
		//从参数获取taskKey
		String taskKeyName = params.getString("taskKey");
		String taskKey = "";
		if (taskKeyName.contains("&")){
			String testStage = variables.get("testStage").getTextValue();
			if ("2".equals(testStage)){
				taskKey = taskKeyName.split("\\&")[0];
			}else if ("1".equals(testStage)){
				taskKey = taskKeyName.split("\\&")[1];
			}else{
				taskKey = taskKeyName.split("\\&")[2];
			}
		}else{
			taskKey = taskKeyName;
		}
		log.info("taskKey----------------"+taskKey);
		FlowTaskComment flowTaskComment = flowTaskCommentService.findByProceInsAndTask(processInstanceId,taskKey);
		if(flowTaskComment != null){
			Long createUserId = flowTaskComment.getCreateUserId();
			R<UserInfo> user = userClient.userInfo(createUserId);
			if (user.isSuccess()&&user.getData()!=null&&user.getData().getUser()!=null&&user.getData().getUser().getId()!=null){
				log.info("发起人account----------------"+user.getData().getUser().getAccount());
				return user.getData().getUser();
			}
		}
		return null;
	}

	/**
	 * 根据角色名称获取所有的邮箱
	 * @param roleName
	 * @return
	 */
	private List<String> findEmailByRole(String roleName){
		//根据角色名称查询所有用户
		R<List<User>> users = userClient.findByRoleName(roleName);
		Set<String> emails = new HashSet<>();
		if (users.isSuccess()&&users.getData()!=null&&users.getData().size()>0){
			for (User user:users.getData()){
				if (user!=null && StringUtil.hasText(user.getEmail())){
					emails.add(user.getEmail());
				}
			}
		}
		return new ArrayList<>(emails);
	}

	/**
	 * 包材角色审批邮箱提醒
	 * @param roleName
	 * @param processName
	 * @param variables
	 */
	private void pkgRoleSendEmail(String roleName,String processName,Map<String, VariableInstance> variables,EmailTemplate tpm){
		//根据角色名称查询所有用户的邮箱
		List<String> emails = findEmailByRole(roleName);
		if (emails.size()>0){
			//获取项目编号和名称
			Map<String,Object> templateParam = getProjectAndName(variables);
			templateParam.put("processName",processName);
			new Thread(()->{
				log.info("包材"+roleName+"审批流程异步发送邮箱任务开始----------->"+ System.currentTimeMillis());
				//发送邮件
				emailCommonUtil.sendMail(emails, tpm.getEmailTheme(), tpm.getEmailTheme(), processTemplate(tpm.getMouldContent(),templateParam));
				log.info("包材"+roleName+"审批流程异步发送邮箱任务结束----------->"+ System.currentTimeMillis());
			}).start();
		}
	}

	/**
	 * 处理远程测试参数
	 * @param variables
	 * @param status
	 * @return
	 */
	private Map<String,Object> handleRemoteParam(Map<String, VariableInstance> variables,String status){
		Map<String,Object> params = new HashMap<>();
		params.put("status",status);
		if (variables.get("planFinishTime")!=null&&StringUtil.hasText(variables.get("planFinishTime").getTextValue())){
			String planFinishTime = variables.get("planFinishTime").getTextValue();
			params.put("planFinishTime",planFinishTime.length()>10?planFinishTime.substring(0,10):planFinishTime);
		}else{
			params.put("planFinishTime","");
		}
		params.put("testNo",variables.get("testNo")!=null?variables.get("testNo").getTextValue():"");
		params.put("deviceName",variables.get("deviceName")!=null?variables.get("deviceName").getTextValue():"");
		params.put("deviceModel",variables.get("deviceModel")!=null?variables.get("deviceModel").getTextValue():"");
		String testType = "";
		if (variables.get("testType")!=null && "1".equals(variables.get("testType").getTextValue())){
			testType = "可行性";
		}else if (variables.get("testType")!=null && "2".equals(variables.get("testType").getTextValue())){
			testType = "样机性能验收";
		}else if (variables.get("testType")!=null && "3".equals(variables.get("testType").getTextValue())){
			testType = "安装demo";
		}
		params.put("testType",testType);
		String deviceType = "";
		if (variables.get("deviceType")!=null && "1".equals(variables.get("deviceType").getTextValue())){
			deviceType = "设备类别A";
		}else if (variables.get("deviceType")!=null && "2".equals(variables.get("deviceType").getTextValue())){
			deviceType = "设备类别B";
		}else if (variables.get("deviceType")!=null && "3".equals(variables.get("deviceType").getTextValue())){
			deviceType = "设备类别C";
		}
		params.put("deviceType",deviceType);
		return params;
	}

	/**
	 * 根据多个用户获取所有的邮箱
	 * @param names
	 * @param variables
	 * @return
	 */
	private List<String> getEmailsByNames(String[] names,Map<String, VariableInstance> variables) {
		List<String> emails = new ArrayList<>();
		for (String name : names) {
			//从流程参数里面获取具体的处理人
			if (StringUtil.isNotBlank(name) && variables.get(name) != null && StringUtil.hasText(variables.get(name).getTextValue())) {
				String handlePersonAccount = variables.get(name).getTextValue();
				log.info("新设备小件下级处理人account-----------" + handlePersonAccount);
				//查询用户
				R<UserInfo> user = userClient.userInfo("000000", handlePersonAccount);
				if (user.isSuccess() && user.getData() != null && user.getData().getUser() != null && user.getData().getUser().getId() != null) {
					User userInfo = user.getData().getUser();
					String email = userInfo.getEmail();
					if (StringUtil.hasText(email)) {
						emails.add(email);
					}
				}
			}
		}
		return emails;
	}

	/**
	 * 根据用户获取邮箱
	 * @param name
	 * @param variables
	 * @return
	 */
	private String getEmailByName(String name,Map<String, VariableInstance> variables) {
		//从流程参数里面获取具体的处理人
		if (StringUtil.isNotBlank(name) && variables.get(name) != null && StringUtil.hasText(variables.get(name).getTextValue())) {
			String handlePersonAccount = variables.get(name).getTextValue();
			log.info("下级处理人account-----------" + handlePersonAccount);
			//查询用户
			R<UserInfo> user = userClient.userInfo("000000", handlePersonAccount);
			if (user.isSuccess() && user.getData() != null && user.getData().getUser() != null && user.getData().getUser().getId() != null) {
				User userInfo = user.getData().getUser();
				return userInfo.getEmail();
			}
		}
		return null;
	}
}
